/**
 * @p.md
 * 
 * ProcessRegistry 模块，负责管理 Actor 进程注册和查找
 */
import { PID } from './pid';
import { Process } from './process';
import { ActorSystem } from './actorSystem';

/**
 * 进程注册表接口，定义了进程的注册、查找和删除操作
 */
export interface IProcessRegistry {
  /**
   * 获取本地地址
   */
  address(): string;
  
  /**
   * 生成下一个唯一 ID
   */
  nextId(): string;
  
  /**
   * 向注册表中添加进程
   * @param process 进程实例
   * @param id 进程 ID
   */
  add(process: Process, id: string): PID;
  
  /**
   * 从注册表中获取进程
   * @param pid 进程 ID
   */
  get(pid: PID): Process | undefined;
  
  /**
   * 从注册表中移除进程
   * @param pid 进程 ID
   */
  remove(pid: PID): void;
  
  /**
   * 获取主机解析 PID
   */
  get hostResolverPid(): PID | undefined;
  
  /**
   * 设置主机解析 PID
   */
  set hostResolverPid(pid: PID | undefined);
  
  /**
   * 通过 ID 解析进程
   * @param id 进程 ID
   * @returns 找到的进程或 undefined
   */
  resolveProcess?(id: string): Process | undefined;
  
  /**
   * 获取所有已注册的进程 ID
   * @returns 进程 ID 数组
   */
  getAllProcesses?(): string[];
  
  /**
   * 设置进程注册表地址
   * @param address 新地址
   */
  _setAddress?(address: string): void;
}

/**
 * 默认进程注册表实现
 */
export class DefaultProcessRegistry implements IProcessRegistry {
  private _processes: Map<string, Process> = new Map();
  private _sequenceId: number = 0;
  private _hostResolverPid?: PID;
  private _address: string;
  private _protocolType: string = 'default'; // 默认协议类型
  private _peerId: string = ''; // libp2p协议下的peerId
  
  /**
   * 构造函数
   * @param system Actor 系统
   * @param address 本地地址，默认为 'local'
   */
  constructor(private readonly system: ActorSystem, address: string = 'local') {
    this._address = address;
  }
  
  /**
   * 获取本地地址
   * @returns 本地地址
   */
  address(): string {
    // 如果是libp2p协议，返回基于peerId的地址
    if (this._protocolType === 'libp2p' && this._peerId) {
      return `libp2p:${this._peerId}`;
    }
    return this._address;
  }
  
  /**
   * 设置协议类型和peerId
   * @param type 协议类型
   * @param peerId libp2p协议下的peerId
   */
  setProtocolType(type: string, peerId?: string): void {
    this._protocolType = type;
    if (peerId) {
      this._peerId = peerId;
    }
    console.log(`[PROCESS_REGISTRY] 设置协议类型: ${type}, peerId: ${peerId || '无'}`);
  }
  
  /**
   * 获取协议类型
   */
  getProtocolType(): string {
    return this._protocolType;
  }
  
  /**
   * 获取peerId
   */
  getPeerId(): string {
    return this._peerId;
  }
  
  /**
   * 生成下一个唯一 ID
   * @returns 唯一 ID
   */
  nextId(): string {
    return (++this._sequenceId).toString();
  }
  
  /**
   * 向注册表中添加进程
   * @param proc 进程实例
   * @param id 进程 ID
   * @returns 新创建的 PID
   */
  add(proc: Process, id: string): PID {
    let pid: PID;
    
    console.log(`[PROCESS_REGISTRY] Adding process with ID: ${id}`);
    
    // 首先检查进程对象是否已经有 PID（包装进程的情况）
    if ('pid' in proc && (proc as any).pid instanceof PID) {
      pid = (proc as any).pid;
      console.log(`[PROCESS_REGISTRY] Process has embedded PID: ${pid.address}/${pid.id}`);
      
      // 使用进程自己的 PID 注册
      const processKey = `${pid.address}/${pid.id}`;
      console.log(`[PROCESS_REGISTRY] Registering with embedded PID, key: ${processKey}`);
      this._processes.set(processKey, proc);
      
      // 返回相同的 PID
      pid.system = this.system;
      return pid;
    }
    
    // 处理远程进程 ID 格式
    if (id === 'remote$0') {
      // 对于远程进程，我们需要从进程对象中获取正确的地址
      const remotePid = (proc as any).pid;
      console.log(`[PROCESS_REGISTRY] Remote process with remoteId, proc.pid=${remotePid?.address}/${remotePid?.id}`);
      
      if (remotePid && remotePid.address) {
        pid = new PID(remotePid.address, id);
        
        const processKey = `${remotePid.address}/${id}`;
        console.log(`[PROCESS_REGISTRY] Registering remote process with ID: ${processKey}`);
        this._processes.set(processKey, proc);
      } else {
        // 回退到默认行为
        pid = new PID(this._address, id);
        
        const processKey = `${this._address}/${id}`;
        console.log(`[PROCESS_REGISTRY] Registering process with ID: ${processKey} (fallback)`);
        this._processes.set(processKey, proc);
      }
    } else if (id.startsWith('remote$')) {
      // 对于带有地址的远程格式，提取地址
      const remoteAddress = id.substring(7); // 移除 'remote$' 前缀
      console.log(`[PROCESS_REGISTRY] Remote process with address in id: ${remoteAddress}`);
      pid = new PID(remoteAddress, 'remote$0');
      
      const processKey = `${remoteAddress}/remote$0`;
      console.log(`[PROCESS_REGISTRY] Registering remote process with ID: ${processKey}`);
      this._processes.set(processKey, proc);
    } else {
      // 对于本地进程，使用本地地址
      pid = new PID(this._address, id);
      
      const processKey = `${this._address}/${id}`;
      console.log(`[PROCESS_REGISTRY] Registering local process with ID: ${processKey}`);
      this._processes.set(processKey, proc);
    }
    
    console.log(`[PROCESS_REGISTRY] Current process registry state:`);
    this._processes.forEach((_, key) => console.log(`  - ${key}`));
    
    pid.system = this.system;
    return pid;
  }
  
  /**
   * 从注册表中获取进程
   * @param pid 进程 ID
   * @returns 进程实例或 undefined (如果不存在)
   */
  get(pid: PID): Process | undefined {
    // 确保 pid 有正确的地址和 ID
    if (!pid) {
      console.warn('[PROCESS_REGISTRY] Attempted to get process with null or undefined PID');
      return undefined;
    }
    
    if (!pid.address || !pid.id) {
      console.warn(`[PROCESS_REGISTRY] Invalid PID format: ${JSON.stringify(pid)}`);
      return undefined;
    }
    
    // 获取进程 key
    let address = pid.address;
    let id = pid.id;
    
    // 处理简单对象格式的 PID
    if (typeof pid === 'object' && !('toString' in pid)) {
      const simplePid = pid as any;
      address = simplePid.address;
      id = simplePid.id;
      console.log(`[PROCESS_REGISTRY] Converting simple object PID to address=${address}, id=${id}`);
    }
    
    // 判断是否为远程 PID
    const isRemote = address !== 'local' && address !== this._address;
    
    // 构建进程查找键
    const processKey = `${address}/${id}`;
    console.log(`[PROCESS_REGISTRY] Resolving process with ID: ${id}, key: ${processKey}`);
    
    // 打印当前可用进程列表，帮助调试
    console.log(`[PROCESS_REGISTRY] Available processes:`, Array.from(this._processes.keys()));
    
    // 首先尝试精确匹配
    let process = this._processes.get(processKey);
    if (process) {
      console.log(`[PROCESS_REGISTRY] Process found with exact match: ${processKey}`);
      return process;
    }
    
    // 如果不是远程进程且使用了local地址，尝试用当前注册表地址查找
    if (!isRemote && address === 'local') {
      const altKey = `${this._address}/${id}`;
      console.log(`[PROCESS_REGISTRY] Trying alternative key: ${altKey}`);
      process = this._processes.get(altKey);
      
      if (process) {
        console.log(`[PROCESS_REGISTRY] Process found with alternative key: ${altKey}`);
        return process;
      }
    }
    
    // 如果是远程 PID，尝试查找对应的远程处理器
    if (isRemote) {
      console.log(`[PROCESS_REGISTRY] Remote PID detected: ${processKey}`);
      
      // 尝试通过系统解析远程进程
      if (this.system && (this.system as any).remote) {
        try {
          console.log(`[PROCESS_REGISTRY] Attempting to resolve remote process via system.remote`);
          const remote = (this.system as any).remote;
          
          if (typeof remote.activatorForAddress === 'function') {
            const activator = remote.activatorForAddress(address);
            if (activator) {
              console.log(`[PROCESS_REGISTRY] Found remote activator for ${address}`);
              return {
                sendUserMessage: (pid: PID, message: any) => {
                  console.log(`[PROCESS_REGISTRY] Forwarding message to remote: ${pid.toString()}`);
                  remote.sendRemoteMessage(pid, message);
                },
                sendSystemMessage: (pid: PID, message: any) => {
                  console.log(`[PROCESS_REGISTRY] Forwarding system message to remote: ${pid.toString()}`);
                  remote.sendRemoteMessage(pid, message);
                },
                stop: () => {
                  console.log(`[PROCESS_REGISTRY] Stopping remote process: ${processKey}`);
                  // 这里可能需要发送停止消息
                }
              };
            }
          }
        } catch (error) {
          console.error(`[PROCESS_REGISTRY] Error resolving remote process:`, error);
        }
      }
      
      // 如果找不到 remote 处理器，检查是否有主机解析器
      if (this._hostResolverPid) {
        console.log(`[PROCESS_REGISTRY] Using host resolver for ${address}`);
        // TODO: 实现主机解析器逻辑
      }
      
      // 最后的尝试：查找任何能处理远程消息的进程
      for (const [key, proc] of this._processes.entries()) {
        if (key.includes('remote')) {
          console.log(`[PROCESS_REGISTRY] Found potential remote handler: ${key}`);
          return proc;
        }
      }
    }
    
    // 尝试查找具有相同ID的进程（无论地址）
    for (const [key, proc] of this._processes.entries()) {
      if (key.endsWith(`/${id}`)) {
        console.log(`[PROCESS_REGISTRY] Found process with matching ID regardless of address: ${key}`);
        return proc;
      }
    }
    
    // 尝试按名称模式匹配
    if (id.includes('$')) {
      const actorName = id.split('$')[0];
      for (const [key, proc] of this._processes.entries()) {
        if (key.includes(`/${actorName}$`)) {
          console.log(`[PROCESS_REGISTRY] Found process with matching actor name pattern: ${key}`);
          return proc;
        }
      }
    }
    
    console.log(`[PROCESS_REGISTRY] Process not found: ${processKey}, will be handled as dead letter`);
    return undefined;
  }
  
  /**
   * 从注册表中移除进程
   * @param pid 进程 ID
   */
  remove(pid: PID): void {
    const processKey = `${pid.address}/${pid.id}`;
    console.log(`Removing process with ID: ${processKey}`);
    this._processes.delete(processKey);
  }
  
  /**
   * 获取主机解析 PID
   */
  get hostResolverPid(): PID | undefined {
    return this._hostResolverPid;
  }
  
  /**
   * 设置主机解析 PID
   */
  set hostResolverPid(pid: PID | undefined) {
    this._hostResolverPid = pid;
  }

  /**
   * 获取所有已注册的进程
   */
  getAllProcesses(): string[] {
    return Array.from(this._processes.keys());
  }

  /**
   * 通过 ID 解析进程
   * @param id 进程 ID
   * @returns 找到的进程或 undefined
   */
  resolveProcess(id: string): Process | undefined {
    const address = this._address;
    const processKey = `${address}/${id}`;
    
    console.log(`[PROCESS_REGISTRY] Resolving process with ID: ${id}, key: ${processKey}`);
    console.log(`[PROCESS_REGISTRY] Available processes:`, Array.from(this._processes.keys()));
    
    const process = this._processes.get(processKey);
    console.log(`[PROCESS_REGISTRY] Process found: ${Boolean(process)}`);
    
    return process;
  }

  /**
   * 设置进程注册表地址
   * @param address 新地址
   */
  _setAddress(address: string): void {
    console.log(`[PROCESS_REGISTRY] 更新地址: ${this._address} -> ${address}`);
    this._address = address;
  }
}

/**
 * 进程注册表工厂，提供创建进程注册表的方法
 */
export class ProcessRegistry {
  private static _instance: IProcessRegistry | null = null;
  private static _system: ActorSystem | null = null;

  /**
   * 初始化进程注册表
   * @param system Actor系统
   * @param address 可选的本地地址
   */
  static initialize(system: ActorSystem, address?: string): void {
    ProcessRegistry._system = system;
    ProcessRegistry._instance = new DefaultProcessRegistry(system, address);
  }

  /**
   * 获取进程注册表实例
   */
  static getInstance(): IProcessRegistry {
    if (!ProcessRegistry._instance) {
      if (!ProcessRegistry._system) {
        throw new Error('ProcessRegistry not initialized. Call initialize() first.');
      }
      ProcessRegistry._instance = new DefaultProcessRegistry(ProcessRegistry._system);
    }
    return ProcessRegistry._instance;
  }

  /**
   * 创建默认进程注册表
   * @param system Actor系统
   * @param address 本地地址
   * @returns 默认进程注册表实例
   * @deprecated 使用 getInstance() 代替
   */
  static createProcessRegistry(system: ActorSystem, address?: string): IProcessRegistry {
    console.warn('Deprecated: Use ProcessRegistry.getInstance() instead');
    return new DefaultProcessRegistry(system, address);
  }

  /**
   * 获取所有已注册的进程
   */
  static getAllProcesses(): string[] {
    if (!ProcessRegistry._instance) {
      return [];
    }
    return (ProcessRegistry._instance as DefaultProcessRegistry).getAllProcesses();
  }
  
  /**
   * 设置协议类型和peerId
   * @param type 协议类型
   * @param peerId libp2p协议下的peerId
   */
  static setProtocolType(type: string, peerId?: string): void {
    if (ProcessRegistry._instance && typeof (ProcessRegistry._instance as any).setProtocolType === 'function') {
      (ProcessRegistry._instance as any).setProtocolType(type, peerId);
    }
  }
  
  /**
   * 获取协议类型
   */
  static getProtocolType(): string {
    if (ProcessRegistry._instance && typeof (ProcessRegistry._instance as any).getProtocolType === 'function') {
      return (ProcessRegistry._instance as any).getProtocolType();
    }
    return 'default';
  }
  
  /**
   * 获取peerId
   */
  static getPeerId(): string {
    if (ProcessRegistry._instance && typeof (ProcessRegistry._instance as any).getPeerId === 'function') {
      return (ProcessRegistry._instance as any).getPeerId();
    }
    return '';
  }
} 